package dm.ast;

import test.envset.GlobalState;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.*;

/**
 * Dm的case表达式，简单情况
 * case valueExpression
 *      when...then...
 *      when...then...
 *      else elseValue
*  end
 *  Dm的case表达式，搜索情况：
 *  case
 *      when...then...
 *      when...then...
 *      else elseValue
 *  end
 *  处于AST中的叶子节点
 */
public class DmCase extends DmExpression{
    //null对应搜索情况；非null对应简单情况
    private DmExpression valueExpression;
    //简单情况时，when中填一般表达式，搜索情况时，when中填布尔表达式，至少有一组值
    private Map<DmExpression , DmExpression> whenThen = new HashMap<DmExpression , DmExpression>();
    //可为Null，此时无else子句
    private DmExpression elseValue;

    @Override
    public void setWidt(){
        if(isCompleted){
            wid_t = 1;
            if(valueExpression != null){
                valueExpression.setWidt();
                wid_t += valueExpression.getWidt();
            }
            if (elseValue != null){
                elseValue.setWidt();
                wid_t += elseValue.getWidt() + 1;
            }
            for(Entry<DmExpression , DmExpression> entry : whenThen.entrySet()){
                entry.getKey().setWidt();
                wid_t += entry.getKey().getWidt() + 1;
                entry.getValue().setWidt();
                wid_t += entry.getValue().getWidt();
            }
        }

    }

    @Override
    public void setDept(){
        if(isCompleted){
            dep_t = 1;
            if(valueExpression != null){
                valueExpression.setDept();
                dep_t = valueExpression.getDept();
            }
            if(elseValue != null){
                elseValue.setDept();
                if(elseValue.getDept() > dep_t){
                    dep_t = elseValue.getDept();
                }
            }
            for(Entry<DmExpression , DmExpression> entry : whenThen.entrySet()){
                entry.getKey().setDept();
                if(entry.getKey().getDept() > dep_t){
                    dep_t = entry.getKey().getDept();
                }
                entry.getValue().setDept();
                if(entry.getValue().getDept() > dep_t){
                    dep_t = entry.getValue().getDept();
                }
            }
        }
    }

    @Override
    public String toSql(){
        StringBuilder sql = new StringBuilder();
        sql.append(" (CASE ");
        sql.append(String.format(getSqlTarget() + "/* w:%d, d:%d, b:%d*/" , wid_t , dep_t , whenThen.size()));
        if(valueExpression != null){
            sql.append(valueExpression.toSql());
        }
        for(Entry<DmExpression , DmExpression> entry : whenThen.entrySet()){
            sql.append(" WHEN ");
            sql.append(entry.getKey().toSql());
            sql.append(" THEN ");
            sql.append(entry.getValue().toSql());
        }
        if(elseValue != null){
            sql.append(" ELSE ");
            sql.append(elseValue.toSql());
        }
        sql.append(" END)");
        return sql.toString();
    }


    @Override
    public void fill(GlobalState globalState){
        if(!isCompleted){
            if(valueExpression != null){
                valueExpression.fill(globalState);
            }
            for(Entry<DmExpression , DmExpression> entry : whenThen.entrySet()){
                entry.getKey().fill(globalState);
                entry.getValue().fill(globalState);
            }
            if(elseValue != null){
                elseValue.fill(globalState);
            }
            isCompleted = true;
        }
    }

    public void setValueExpression(DmExpression valueExpression) {
        this.valueExpression = valueExpression;
    }

    public void addWhenThen(DmExpression when , DmExpression then){
        whenThen.put(when ,then);
    }
    public void setElseValue(DmExpression elseValue) {
        this.elseValue = elseValue;
    }

    public void fixErr4097(){
        if(valueExpression != null){
            valueExpression.fixErr4097();
        }
        if(elseValue != null){
            elseValue.fixErr4097();
        }
        for(Entry<DmExpression , DmExpression> entry : whenThen.entrySet()){
            entry.getKey().fixErr4097();
            entry.getValue().fixErr4097();
        }
    }
}
